/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2012-2020. All rights reserved.
 */

package com.huawei.chengdu.meetingdemo.view.dialogs;

import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

import com.huawei.chengdu.meetingdemo.util.LogUtil;
import com.huawei.chengdu.meetingdemo.presenter.MeetingManager;

import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 类名：FloatWindowBase
 * 描述：悬浮窗抽象基类
 */
public abstract class FloatWindowBase implements IFloatWindow {
    private static final String TAG = "FloatWindowBase";

    private static List<FloatWindowBase> showingWindowsList = new CopyOnWriteArrayList<>();

    /**
     * 窗口是否在显示
     */
    public boolean isShow = false;

    /**
     * 窗口管理者
     */
    protected WindowManager mWindowManager;

    /**
     * 布局参数
     */
    protected WindowManager.LayoutParams wmParams;

    /**
     * 上下文
     */
    protected Context mContext;

    /**
     * view根布局
     */
    protected View mRootView;

    /**
     * 忽略外部点击事件的视图
     */
    private View anchorView;

    /**
     * 弹框左上角X坐标
     */
    protected int posX;

    /**
     * 弹框左上角Y坐标
     */
    protected int posY;

    /**
     * 弹框宽度
     */
    protected int dlgWidth;

    /**
     * 弹框高度
     */
    protected int dlgHeight;

    /**
     * 屏幕宽
     */
    protected int screenHeight = 2160;

    /**
     * 屏幕高
     */
    protected int screenWidth = 3840;

    /**
     * 监听弹框关闭
     */
    protected DismissWindowListener dismissWindowListener;

    public FloatWindowBase(Context context) {
        mContext = context;
        floatWindowSetting();
        initRootView();
    }

    private void floatWindowSetting() {
        // 初始化窗口管理服务
        if (mWindowManager == null && (mContext.getSystemService(Context.WINDOW_SERVICE) instanceof WindowManager)) {
            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        }

        // 初始化窗口布局参数
        if (wmParams == null) {
            wmParams = new WindowManager.LayoutParams();
            // 设置图片格式，效果为背景透明
            wmParams.format = PixelFormat.RGBA_8888;

            wmParams.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

            wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        }
    }

    /**
     * 设置安全属性，有密码的弹框都要调用该方法，截止截屏
     */
    protected void addSecureFlag() {
        if (wmParams != null) {
            wmParams.flags = wmParams.flags | WindowManager.LayoutParams.FLAG_SECURE;
        }
    }

    /**
     * 获取跟布局id
     *
     * @return 布局id
     */
    protected abstract int getLayoutId();

    /**
     * 获取子类的名字
     *
     * @return 子类的名字
     */
    protected abstract String getChildName();

    private void initRootView() {
        mRootView = LayoutInflater.from(mContext).inflate(getLayoutId(), null);
        mRootView.setOnTouchListener((view, event) -> {
            if (event != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                LogUtil.info(TAG + "click outside window: " + event);
                return doOutSideTouch(event);
            }
            return true;
        });
    }

    /**
     * 处理外部点击事件
     *
     * @param event 事件
     * @return 是否处理
     */
    protected boolean doOutSideTouch(MotionEvent event) {
        boolean isAnchorClicked = false;
        if (anchorView != null) {
            float touchX = event.getRawX();
            float touchY = event.getRawY();
            int[] location = new int[2];
            anchorView.getLocationOnScreen(location);
            isAnchorClicked = touchX >= location[0] && touchX <= location[0] + anchorView.getMeasuredWidth()
                    && touchY >= location[1] && touchY <= location[1] + anchorView.getMeasuredHeight();
        }
        if (!isAnchorClicked) {
            release();
        } else {
            LogUtil.info(TAG + "click outside window");
        }
        return true;
    }

    /**
     * 设置外部点击视图
     *
     * @param anchorView view
     */
    public void setAnchorView(View anchorView) {
        this.anchorView = anchorView;
    }

    /**
     * 窗口title
     *
     * @param tag 设置字段
     * @return 返回字段
     */
    protected String toWindowTitleString(String tag) {
        if (TextUtils.equals(tag, "Toast")) {
            return tag;
        }
        // 下面tag之前的前缀为设置title的固定字段，请误改动
        return "Window - " + "com.device.idea.meetingui" + "/" + tag;
    }

    /**
     * 设置windowmanager title参数
     *
     * @param title 设置值
     */
    protected void setWmTitleParams(String title) {
        String resultTitle = toWindowTitleString(title);
        LogUtil.debug(TAG + " resultTitle:" + resultTitle);
        wmParams.setTitle(resultTitle);
    }

    /**
     * 设置windowmanager位置参数
     *
     * @param gravity 重心
     * @param xCoordinate x坐标
     * @param yCoordinate y坐标
     * @param width 宽度
     * @param height 高度
     */
    protected void setWmPositionParams(int gravity, int xCoordinate, int yCoordinate, int width, int height) {
        wmParams.gravity = gravity;
        wmParams.x = xCoordinate;
        wmParams.y = yCoordinate;
        wmParams.width = width;
        wmParams.height = height;
    }

    @Override
    public void showFloatWindow() {
        LogUtil.debug(TAG + getChildName() + " showFloatWindow");
        if (mRootView == null || wmParams == null || mWindowManager == null) {
            LogUtil.error(TAG + "showFloatWindow error, wm or wmParams or mWindowView is null");
            return;
        }
        if (isShow) {
            LogUtil.error(TAG + getChildName() + " showFloatWindow isShow==true, so return");
            return;
        }
        FloatWindowBase.releaseAllWindows();
        if (MeetingManager.getInstance().isInConf()) {
            mWindowManager.addView(mRootView, wmParams);
            showingWindowsList.add(this);
            isShow = true;
        }
    }

    @Override
    public void release() {
        LogUtil.debug(TAG + getChildName() + "release");
        if (!isShow) {
            LogUtil.debug(TAG + getChildName() + " isShow==false, so return");
            return;
        }

        if (mRootView != null && mWindowManager != null) {
            mWindowManager.removeView(mRootView);
            showingWindowsList.remove(this);
            isShow = false;
        }
        if (dismissWindowListener != null) {
            dismissWindowListener.dismiss();
        }
    }

    /**
     * 释放所有悬浮窗
     */
    public static void releaseAllWindows() {
        LogUtil.debug(TAG + "releaseAllWindows");
        for (FloatWindowBase floatWindow : showingWindowsList) {
            if (floatWindow != null) {
                floatWindow.release();
            }
        }
    }

    /**
     * 阿拉伯语 是否从左到右
     *
     * @return 返回是否从左到右
     */
    public static boolean isLtrDirection() {
        return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
            == ViewGroup.LAYOUT_DIRECTION_LTR;
    }

    /**
     * 设置OPS及Type-C投屏触控屏蔽区域位置信息
     *
     * @param isShow 是否显示弹框
     * @param title 具体的dialog弹框TAG
     */
    public void sendRectBroadCast(boolean isShow, String title) {
        Rect rect;
        if (isShow) {
            rect = new Rect((screenWidth - dlgWidth) / 2, (screenHeight - dlgHeight) / 2,
                    (screenWidth - dlgWidth) / 2 + dlgWidth,
                    (screenHeight - dlgHeight) / 2 + dlgHeight);
        } else {
            rect = new Rect(0, 0, 0, 0);
        }
    }

    /**
     * 监听弹窗window消失
     *
     */
    public interface DismissWindowListener {
        /**
         * 弹框消失方法
         */
        void dismiss();
    }

    /**
     * 设置弹框关闭监听
     *
     * @param dismissWindowListener 监听
     */
    public void setDismissWindowListener(DismissWindowListener dismissWindowListener) {
        this.dismissWindowListener = dismissWindowListener;
    }
}
